﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Wintellect.PowerCollections;

namespace TheatreManagementSystem
{
   public class MainTheatreSystem
    {
        private Dictionary<string, Ticket> dictIdTicket = new Dictionary<string, Ticket>();
        private MultiDictionary<string, Ticket> dictCustomerTicket = new MultiDictionary<string, Ticket>(true);
        private MultiDictionary<string, Ticket> dictSellerTicket = new MultiDictionary<string, Ticket>(true);
        private MultiDictionary<Play, Ticket> dictPerfTicket = new MultiDictionary<Play, Ticket>(true);

        public Dictionary<string, Ticket> DictIdTicket 
        {
            get{ return this.dictIdTicket; }
        }
        public MultiDictionary<string, Ticket> DictCustomerTicket
        {
            get { return this.dictCustomerTicket; }
        }
        public MultiDictionary<string, Ticket> DictSellerTicket
        {
            get { return this.dictSellerTicket; }
        }
        public MultiDictionary<Play, Ticket> DictPerfTicket
        {
            get { return this.dictPerfTicket; }
        }
       
        List<Customer> allCustomers = new List<Customer>()
           {
               new RegularCustomer(49, "Jane", "Smith"),
               new RegularCustomer(1, "John", "Smith")
           };

       List<Employee> allEmployees=new List<Employee>()
           {new Seller("Mary", "Smith", "1234")};
       List<Performance> allPerformances = new List<Performance>();
   
       List<Hall> allHalls = new List<Hall>()
   {
          new Hall("Great Hall", new char[,]
            { 
                {'=','=','=','=','=','=','=','=','=','=','=','=','=','=','=','=','=','=','=','=' },
                {' ','=','=','=','=','=','=','=','=','=','=','=','=','=','=','=','=','=','=',' ' },
                {' ','=','=','=','=','=','=','=','=','=','=','=','=','=','=','=','=','=','=',' ' },
                {' ','=','=','=','=','=','=','=','=','=','=','=','=','=','=','=','=','=','=',' ' },
                {' ',' ','=','=','=','=','=','=','=','=','=','=','=','=','=','=','=','=',' ',' ' },
                {' ',' ','=','=','=','=','=','=','=','=','=','=','=','=','=','=','=','=',' ',' ' },
                {' ',' ','=','=','=','=','=','=','=','=','=','=','=','=','=','=','=','=',' ',' ' },
                {' ',' ','=','=','=','=','=','=','=','=','=','=','=','=','=','=','=','=',' ',' ' },
                {' ',' ',' ','=','=','=','=','=','=','=','=','=','=','=','=','=','=',' ',' ',' ' },
                {' ',' ',' ','=','=','=','=','=','=','=','=','=','=','=','=','=','=',' ',' ',' ' }, 
            }),
             new Hall("Medium Hall", new char[,]
            { 
                {'=','=','=','=','=','=','=','=','=','=','=','=','=','=','=' },
                {' ','=','=','=','=','=','=','=','=','=','=','=','=','=',' ' },
                {' ','=','=','=','=','=','=','=','=','=','=','=','=','=',' ' },
                {' ','=','=','=','=','=','=','=','=','=','=','=','=','=',' ' },
                {' ',' ','=','=','=','=','=','=','=','=','=','=','=',' ',' ' },
                {' ',' ','=','=','=','=','=','=','=','=','=','=','=',' ',' ' },
                {' ',' ','=','=','=','=','=','=','=','=','=','=','=',' ',' ' },
                {' ',' ','=','=','=','=','=','=','=','=','=','=','=',' ',' ' },
                {' ',' ',' ','=','=','=','=','=','=','=','=','=',' ',' ',' ' },
                {' ',' ',' ','=','=','=','=','=','=','=','=','=',' ',' ',' ' }, 
            }),
             new Hall("Small Hall", new char[,]
            {                                                                    
                {'=','=','=','=','=','=','=','=','=','=','=' },                  
                {' ','=','=','=','=','=','=','=','=','=',' ' },                  
                {' ','=','=','=','=','=','=','=','=','=',' ' },                  
                {' ','=','=','=','=','=','=','=','=','=',' ' },                  
                {' ',' ','=','=','=','=','=','=','=',' ',' ' },                  
                {' ',' ','=','=','=','=','=','=','=',' ',' ' },                  
                {' ',' ','=','=','=','=','=','=','=',' ',' ' },                  
                {' ',' ','=','=','=','=','=','=','=',' ',' ' },                  
                {' ',' ',' ','=','=','=','=','=',' ',' ',' ' },                  
                {' ',' ',' ','=','=','=','=','=',' ',' ',' ' },                  
            })
   };
       public Ticket CreateNewTicket(Customer customer, Performance performance, Seat seat,Seller seller)
       {
           Ticket ticket = TicketFactory.CreateNewTicket(customer, performance, seat, seller);
           dictIdTicket.Add(ticket.UniqueIdentifier, ticket);
           dictCustomerTicket.Add((customer.FirstName + " " + customer.LastName), ticket);
           dictSellerTicket.Add(seller.ReturnFullName(), ticket);
           dictPerfTicket.Add(performance.NameOfPlay,ticket);

           CheckForCustomerTransform(customer);

           return ticket;
       }

       public Ticket CreateNewTicket(Performance performance, Seat seat, Seller seller)
       {
           Ticket ticket = TicketFactory.CreateNewTicket(performance, seat, seller);
           dictIdTicket.Add(ticket.UniqueIdentifier, ticket);
           dictSellerTicket.Add(seller.ReturnFullName(), ticket);
           dictPerfTicket.Add(performance.NameOfPlay, ticket);
           return ticket;
       }

#region Event for customer transformation
       private void CheckForCustomerTransform(Customer customer)
       {
           if (customer.IsThresholdReached())
           {
               ThresholdReached += customer_ThresholdReached;
               ThresholdReachedEventArgs args = new ThresholdReachedEventArgs();
               args.customer = customer;
               ThresholdReached(this, args);
           }
       }

       public event EventHandler<ThresholdReachedEventArgs> ThresholdReached;

        void customer_ThresholdReached(object sender, ThresholdReachedEventArgs e)
        {
            Customer newCustomer;
            if (e.customer is SilverCustomer)
            {
                newCustomer = new GoldCustomer(e.customer.FirstName, e.customer.LastName, e.customer.telephoneNumber);
            }
            else //if(e.customer is RegularCustomer)
            {
                newCustomer = new SilverCustomer(e.customer.FirstName, e.customer.LastName, e.customer.telephoneNumber);
            }

 	        allCustomers.Remove(e.customer);
            allCustomers.Add(newCustomer);
        }

        public class ThresholdReachedEventArgs : EventArgs
        {
            public Customer customer { get; set; }
        }

#endregion

       public void AddNewHall(Hall newhall)
       {
           this.allHalls.Add(newhall);
       }
       public void AddNewEmployee(Employee newEmployee)
       {
           this.allEmployees.Add(newEmployee);
       }
       public void AddNewCustomer(Customer newCustomer)
       {
           this.allCustomers.Add(newCustomer);
       }
       public void AddNewPerformance(Performance performance)
       {
           this.allPerformances.Add(performance);
       }

       public Performance ReturnPerformance(DateTime time, Play play)
       {
           foreach (Performance performance in allPerformances)
           {
               if (performance.DateOfPerformance == time && play == performance.NameOfPlay)
               {
                   return performance;
               }
           }

           return null;
       }

       public Customer ReturnCustomerByName(string name)
       {
           var customers =
               from customer in allCustomers
               where customer.FirstName + " " + customer.LastName == name
               select customer;
            if (customers.Count() == 0)
           {
               return null;
           }
           else
           {
               return customers.First();
           }
           
       }
       public Seller ReturnSellerByName(string name)
       {
           var sellers =
               from seller in allEmployees
               where seller is Seller
               where seller.ReturnFullName() == name
               select seller;
            if (sellers.Count() == 0)
           {
               return null;
           }
           else
           {
               return (Seller)sellers.First();
           }
       }

       public Hall ReturnHallByName(string name)
       {
           return this.allHalls.Find(x => x.Name == name);
       }
    }
}
